/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.store.client.subcomponents;

import java.util.ArrayList;
import java.util.List;

import com.elf.gwt.common.client.GWTCommerceCommonConstants;
import com.elf.gwt.common.client.callback.OnBuiltCallback;
import com.elf.gwt.common.client.callback.SubComponentCallback;
import com.elf.gwt.common.client.components.CommonSimpleComponent;
import com.elf.gwt.common.client.model.AccountMetaModel;
import com.elf.gwt.common.client.model.AccountModel;
import com.elf.gwt.common.client.model.AddressModel;
import com.elf.gwt.common.client.subcomponent.CommonSubComponent;
import com.elf.gwt.store.client.GWTCommerceConstants;
import com.elf.gwt.store.client.StoreComponentController;
import com.elf.gwt.store.client.components.AccountComponent;
import com.elf.gwt.store.client.components.CheckoutComponent;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;

/**
 *  Managed Addresses.
 */
public class AccountAddressSubComponent extends StoreSubComponent
{	
	protected DialogBox dialogBox;

	/**
	 * Constructor
	 */
	public AccountAddressSubComponent(
			StoreComponentController controller, 
			SubComponentCallback callback, 
			String superAction)
	{
		super(controller, "AccountComponent", superAction, callback);
		if (accountComponent == null) accountComponent = (AccountComponent)controller.getComponent("AccountComponent");
		this.superAction = superAction;
		build();
	}

	public void build()
	{
		AccountModel accountModel = accountComponent.getAccountModel();
		AccountMetaModel accountMetaModel = accountComponent.getAccountMetaModel();
		thisComponent.clear();
		GWTCommerceConstants constants = controller.getStoreConstants();
		GWTCommerceCommonConstants commonConstants = controller.getCommonConstants();
		List<AddressModel> addresses = accountModel.getAddresses();
		int sz = addresses.size();
		Grid grid = new Grid(sz+1, 3);
		grid.setStyleName(handle + "BodyTable");
		CellFormatter cf = grid.getCellFormatter();
		cf.setWidth(0, 1, "100%");
		if (superAction.equals(CheckoutComponent.Checkout))
			grid.setText(0, 0, constants.CheckoutComponentAction());
		else
			grid.setText(0, 0, constants.AccountComponentPrimary());
			
		grid.setText(0, 1, constants.AccountComponentAddress());
		grid.setText(0, 2, constants.AccountComponentButtons());

		cf.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
		cf.setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
		cf.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_CENTER);
		cf.setStyleName(0, 0, handle + "BodyTableTitle");
		cf.setStyleName(0, 1, handle + "BodyTableTitle");
		cf.setStyleName(0, 2, handle + "BodyTableTitle");
		int row = 1;
		for (int i = 0; i<sz+1; i++)
		{
			boolean primary = false;
			AddressModel amodel;
			if (i == 0)
			{
				amodel = accountModel.getDefaultAddress();
				primary = true;
			}
			else
			{
				amodel = addresses.get(i-1);
				if (amodel.getId() == accountModel.getDefaultAddress().getId()) continue;
			}
			String strAddress = "";
			if (accountMetaModel.isDisplayCompany()) strAddress += amodel.getCompany() + "<br/>";
			strAddress += amodel.getFirstname() + "&nbsp;" + amodel.getLastname() + "<br/>";
			strAddress += amodel.getStreet() + "<br/>";
			if (accountMetaModel.isDisplaySuburb()) strAddress += amodel.getSuburb() + "<br/>";
			strAddress += amodel.getCity();
			if (accountMetaModel.isDisplayState()) strAddress += ", " + amodel.getState() + " ";
			strAddress += amodel.getPostcode() + "<br/>";
			strAddress += amodel.getCountry();
			InlineHTML addressLabel = new InlineHTML(strAddress);
			grid.setWidget(row, 1, addressLabel);

			if (superAction.equals(CheckoutComponent.Checkout))
			{
				Button selectButton = new Button(controller.getCommonConstants().Select(), selectClickHandler);

				selectButton.addStyleName(handle + "BodyTableButton");
				selectButton.addStyleName("index:" + amodel.getId());
				grid.setWidget(row, 0, selectButton);
			}
			else
			{
				String strPrimary = commonConstants.No();
				if (primary) strPrimary = commonConstants.Yes();
				grid.setText(row, 0, strPrimary);
			}
			cf.setHorizontalAlignment(row, 0, HasHorizontalAlignment.ALIGN_CENTER);
			cf.setHorizontalAlignment(row, 1, HasHorizontalAlignment.ALIGN_CENTER);
			cf.setHorizontalAlignment(row, 2, HasHorizontalAlignment.ALIGN_CENTER);
			cf.setWidth(row, 1, "100%");
			cf.setStyleName(row, 0, handle + "BodyTableCell");
			cf.setStyleName(row, 1, handle + "BodyTableCell");
			cf.setStyleName(row, 2, handle + "BodyTableCell");

			VerticalPanel vpanel3 = new VerticalPanel();
			Button editButton = new Button(controller.getCommonConstants().Edit(), editClickHandler);

			editButton.addStyleName(handle + "BodyTableButton");
			editButton.addStyleName("index:" + amodel.getId());
			vpanel3.add(editButton);
			vpanel3.setCellHorizontalAlignment(editButton, HasHorizontalAlignment.ALIGN_CENTER);

			Button deleteButton = new Button(controller.getCommonConstants().Delete(), deleteClickHandler);

			deleteButton.addStyleName(handle + "BodyTableButton");
			deleteButton.addStyleName("index:" + amodel.getId());
			vpanel3.add(deleteButton);
			vpanel3.setCellHorizontalAlignment(deleteButton, HasHorizontalAlignment.ALIGN_CENTER);
			grid.setWidget(row, 2, vpanel3);
			row++;
		}			
		thisComponent.add(grid);	
		HorizontalPanel hpanel = new HorizontalPanel();


		Button addButton = new Button(controller.getStoreConstants().AccountComponentAddAddress(), 
				new ClickHandler() {
					public void onClick(ClickEvent event) {
						AccountModel accountModel = accountComponent.getAccountModel();
						AccountMetaModel accountMetaModel = accountComponent.getAccountMetaModel();
						if (accountModel.getAddresses().size() < accountMetaModel.getAddressBookEntriesMax()) 
						{
							AddressModel addressModel = new AddressModel();
							addressModel.setCountry(accountModel.getDefaultAddress().getCountry());
							DialogBox dialogBox = editDialogBox(addressModel);
							dialogBox.center();
							dialogBox.show();
						}
						else
						{
							Window.alert("Maximum # of Addresses has been reached: " + accountMetaModel.getAddressBookEntriesMax());
						}
					}}
		);
		hpanel.add(addButton);

		Button cancelButton = new Button(controller.getCommonConstants().GoBack(), 
				new ClickHandler() {
					public void onClick(ClickEvent event) {
						
						if (!superAction.equals(CheckoutComponent.Checkout))
							setSuperAction(AccountComponent.ViewAccount);
						getCallback().onNavigate(thisComponent);
					}}
		);
		hpanel.add(cancelButton);
		hpanel.setCellHorizontalAlignment(cancelButton, HasHorizontalAlignment.ALIGN_RIGHT);
		hpanel.setWidth("100%");
		thisComponent.add(hpanel);

		thisComponent.add(new InlineHTML("<br/>"));
		thisComponent.add(new InlineHTML(constants.AccountComponentAddressBookDescription()));
	}

	/**
	 * 
	 */
	ClickHandler editClickHandler = new ClickHandler() {
		public void onClick(ClickEvent event) {
			AccountModel accountModel = accountComponent.getAccountModel();
			AccountMetaModel accountMetaModel = accountComponent.getAccountMetaModel();
			if (accountModel.getAddresses().size() < accountMetaModel.getAddressBookEntriesMax()) 
			{
				Widget source = (Widget)event.getSource();
				String stylenames = source.getStyleName();
				int loc = stylenames.indexOf("index:");
				stylenames = stylenames.substring(loc+6);
				loc = stylenames.indexOf(" ");
				if (loc > -1) stylenames = stylenames.substring(0, loc);
				int id = Integer.parseInt(stylenames);

				AddressModel addressModel = accountModel.getAddressById(id);
				DialogBox dialogBox = editDialogBox(addressModel);
				dialogBox.center();
				dialogBox.show();
			}
			else
			{
				Window.alert("Maximum # of Addresses has been reached: " + accountMetaModel.getAddressBookEntriesMax());
			}
		}
	};

	/**
	 * 
	 */
	ClickHandler deleteClickHandler = new ClickHandler() {
		public void onClick(ClickEvent event) {
			AccountModel accountModel = accountComponent.getAccountModel();

			Widget source = (Widget)event.getSource();
			String stylenames = source.getStyleName();
			int loc = stylenames.indexOf("index:");
			stylenames = stylenames.substring(loc+6);
			loc = stylenames.indexOf(" ");
			if (loc > -1) stylenames = stylenames.substring(0, loc);
			int id = Integer.parseInt(stylenames);

			AddressModel addressModel = accountModel.getAddressById(id);
			accountModel.setEditAddress(addressModel);

			if (superAction.equals(CheckoutComponent.Checkout))
			{
				accountComponent.setAction(AccountComponent.DeleteAddress);
				List<OnBuiltCallback> callbacks = new ArrayList<OnBuiltCallback>();
				callbacks.add(componentCallback);
				accountComponent.setCallbacks(callbacks);
				accountComponent.build(true);
			}
			else
			{
				superAction = AccountComponent.DeleteAddress;
				getCallback().onSuccess(thisComponent);
			}
		}
	};


	/**
	 * 
	 */
	ClickHandler selectClickHandler = new ClickHandler() {
		public void onClick(ClickEvent event) {
			AccountModel accountModel = accountComponent.getAccountModel();
			Widget source = (Widget)event.getSource();
			String stylenames = source.getStyleName();
			int loc = stylenames.indexOf("index:");
			stylenames = stylenames.substring(loc+6);
			loc = stylenames.indexOf(" ");
			if (loc > -1) stylenames = stylenames.substring(0, loc);
			int id = Integer.parseInt(stylenames);

			AddressModel addressModel = accountModel.getAddressById(id);
			accountModel.setEditAddress(addressModel);
			getCallback().onSuccess(thisComponent);
		}
	};

	/**
	 * 
	 * @return
	 */
	protected DialogBox getDialogBox()
	{
		return dialogBox;
	}

	/**
	 * 
	 * @param amodel
	 * @return
	 */
	protected DialogBox editDialogBox(AddressModel addressModel) {
		AccountModel accountModel = accountComponent.getAccountModel();
		dialogBox = new DialogBox();
		dialogBox.setWidth("400px");
		if (addressModel.getId() == 0)
			dialogBox.setText(getController().getStoreConstants().AccountComponentAddAddress());
		else
			dialogBox.setText(getController().getStoreConstants().AccountComponentEditAddress());
		accountModel.setEditAddress(addressModel);
		AccountCreateSubComponent editForm = new AccountCreateSubComponent(
				controller,
				addressModel,
				subComponentCallback, 
				AccountComponent.AddressBook);

		dialogBox.setWidget(editForm);
		dialogBox.setStyleName("AccountComponentDialogBox");
		// Return the dialog box
		return dialogBox;
	}

	/**
	 * 
	 */
	protected SubComponentCallback subComponentCallback = 
		new SubComponentCallback() {
		public void onNavigate(CommonSubComponent subComponent) {
			dialogBox.hide();
			if (!superAction.equals(CheckoutComponent.Checkout))
				getCallback().onNavigate(subComponent);
		}

		public void onSuccess(CommonSubComponent subComponent) {
			dialogBox.hide();
			if (superAction.equals(CheckoutComponent.Checkout))
			{
				accountComponent.setAction(AccountComponent.AddressBook);
				List<OnBuiltCallback> callbacks = new ArrayList<OnBuiltCallback>();
				callbacks.add(componentCallback);
				accountComponent.setCallbacks(callbacks);
				accountComponent.build(true);
			}
			else
			{
				getCallback().onSuccess(subComponent);
			}
		}

		public void onError(CommonSubComponent subComponent, Throwable exception) {}
	};

	protected OnBuiltCallback componentCallback = 
		new OnBuiltCallback()
	{
		public void onBuilt(CommonSimpleComponent component)
		{
			GWT.log("AccountAddressSubComponent componentCallback onBuilt");
			AccountAddressSubComponent comp = (AccountAddressSubComponent)thisComponent;
			comp.build();
			component.setCallbacks(null);
		}
	};
}
